/**
 * @file tmer.c
 * @brief 定时器驱动文件
 * @details 实现定时器初始化、中断处理、计时器显示等功能
 * @author 开发者
 * @date 创建日期
 */

#include "tmer.h"

/**
 * @brief 定时器1初始化函数
 * @details 配置TIMER6定时器，设置预分频器和周期，使能中断
 */
void timer1_init(void)
{
    rcu_periph_clock_enable(RCU_TIMER6);  // 使能TIMER6时钟
    timer_deinit(TIMER6);                 // 反初始化TIMER6
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);	// 4��Ƶ
    timer_parameter_struct tm;            // 定时器参数结构体
    timer_struct_para_init(&tm);          // 初始化定时器参数结构体

    tm.prescaler = 10000;                 // 预分频器值
    tm.period = 16800 - 1;                // 周期值
    timer_init(TIMER6,&tm);               // 初始化TIMER6
    timer_interrupt_enable(TIMER6,TIMER_INT_UP);  // 使能更新中断
    nvic_irq_enable(TIMER6_IRQn,6,0);    // 使能NVIC中断，优先级6
    timer_enable(TIMER6);                 // 使能TIMER6
}

/**
 * @brief 定时器显示函数声明
 */
void start_timer_show();
/**
 * @brief TIMER6中断服务函数
 * @details 处理定时器更新中断，调用显示函数
 */
void TIMER6_IRQHandler(void) {
    if(timer_interrupt_flag_get(TIMER6,TIMER_INT_FLAG_UP) == 1) {
        start_timer_show();  // 调用定时器显示函数
        timer_interrupt_flag_clear(TIMER6,TIMER_INT_FLAG_UP);  // 清除中断标志
    }
}
/* 外部队列句柄声明 */
extern QueueHandle_t  TRK_TRP_Stust;    // 轨迹航点状态队列
extern QueueHandle_t EXTI_AND_TIMER;    // 外部中断和定时器队列
extern QueueHandle_t timer_syn;         // 定时器同步队列
extern int TRDh_num;                    // 轨迹小时数
extern int TRDm_num;                    // 轨迹分钟数
/**
 * @brief 定时器显示函数
 * @details 处理定时器显示、轨迹记录、数据保存等功能
 */
void start_timer_show() {
    static int TRDh_num = 0;             // 轨迹小时数（静态变量）
    static int syn = 0;                  // 同步标志
    static int TRDm_num = 0;             // 轨迹分钟数（静态变量）
    /* 初始化同步，从备份寄存器读取保存的数据 */
    if(syn == 0) {
        if(RTC_BKP3 != 0) {
            TRDh_num = RTC_BKP3;         // 从备份寄存器读取小时数
        }
        if(RTC_BKP4 != 0) {
            TRDm_num = RTC_BKP4;         // 从备份寄存器读取分钟数
        }
        rcu_periph_clock_disable(RCU_PMU);  // 禁用电源管理单元时钟
        pmu_backup_write_disable();         // 禁用备份域写操作
        syn = 1;                            // 设置同步标志
    }
    /* 从队列接收数据 */
    BaseType_t xTaskWokenByReceive = pdFALSE;  // 任务唤醒标志
    static uint8_t recv_num = 0;              // 接收到的数据
    xQueueReceiveFromISR( EXTI_AND_TIMER,     // 从ISR接收队列数据
                          &recv_num,
                          &xTaskWokenByReceive);
    if( xTaskWokenByReceive != pdFALSE ) {
        /* 我们应该切换上下文，使ISR返回到不同的任务。
           注意：这取决于您使用的端口。请检查您的端口的文档和示例。 */
        taskYIELD ();
    }
    
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;  // 高优先级任务唤醒标志

    /* 计时器变量 */
    static int s_num = 0;                    // 秒数
    static int m_num = 0;                    // 分钟数
    static int h_num = 0;                    // 小时数
    static uint8_t TRK_TRP_SEND_FLAG = 0;    // 轨迹航点发送标志
    static uint8_t send_num = 0;             // 发送的数据
    /* 处理开始计时信号（recv_num == 10） */
    if(recv_num == 10) {
        send_num = 10;
        if(TRK_TRP_SEND_FLAG == 0) {
            xQueueSendFromISR( TRK_TRP_Stust, &send_num, &xHigherPriorityTaskWoken );  // 发送开始信号
            if( xHigherPriorityTaskWoken ) {
                portYIELD_FROM_ISR (xHigherPriorityTaskWoken);  // 从ISR进行任务切换
            }
            TRK_TRP_SEND_FLAG = 1;  // 设置发送标志
        }
        
        /* 计时器递增 */
        s_num ++;  // 秒数递增
        if(s_num >= 60) {
            s_num = 0;   // 秒数清零
            m_num += 1;  // 分钟数递增
        }
        if(m_num >= 60) {
            m_num = 0;   // 分钟数清零
            h_num += 1;  // 小时数递增
        }
    }

    /* 处理停止计时信号（recv_num == 20） */
    if(recv_num == 20) {
        send_num = 20;
        if(TRK_TRP_SEND_FLAG == 1) {
            xQueueSendFromISR( TRK_TRP_Stust, &send_num, &xHigherPriorityTaskWoken );  // 发送停止信号
            if( xHigherPriorityTaskWoken ) {
                portYIELD_FROM_ISR (xHigherPriorityTaskWoken);  // 从ISR进行任务切换
            }
            TRK_TRP_SEND_FLAG = 0;  // 清除发送标志
        }
        
        /* 累加轨迹时间 */
        TRDm_num += m_num;  // 累加分钟数
        if(TRDm_num>=60) {
            TRDh_num = TRDm_num/60;  // 计算小时数
            TRDm_num = TRDm_num%60;  // 计算剩余分钟数
        }
        TRDh_num+=h_num;  // 累加小时数
        
        /* 重置计时器 */
        s_num = 0;
        m_num = 0;
        h_num = 0;
        
        /* 保存数据到备份寄存器 */
        rcu_periph_clock_enable(RCU_PMU);   // 使能电源管理单元时钟
        pmu_backup_write_enable();          // 使能备份域写操作
        RTC_BKP3 = TRDh_num;               // 保存小时数到备份寄存器
        RTC_BKP4 = TRDm_num;               // 保存分钟数到备份寄存器
        rcu_periph_clock_disable(RCU_PMU);  // 禁用电源管理单元时钟
        pmu_backup_write_disable();         // 禁用备份域写操作
    }
    /* 格式化显示字符串 */
    char TIMERHMS[10] = {0};  // 计时器时间显示缓冲区
    char TRDHMS[10] = {0};    // 轨迹时间显示缓冲区
    sprintf(TIMERHMS,"%02d.%02d.%02d",h_num,m_num,s_num);  // 格式化计时器时间
    sprintf(TRDHMS,"%02d.%02d",TRDh_num,TRDm_num);         // 格式化轨迹时间
    
    /* 更新UI显示 */
    lv_label_set_text(ui_timerbegin,TIMERHMS);  // 更新计时器显示标签
    lv_label_set_text(ui_TRD1,TRDHMS);          // 更新轨迹时间显示标签

#ifdef TIMER_DEBUG
    printf("%s \n",tmr);  // 调试信息打印
#endif
}
